#include "com_gipsve_GipsVENative.h"
#include "jni_api.h"
#include "libgipsve_apis.h"
#pragma comment(lib, "LibGIPS_WebRTC.lib")

struct VEMode
{
	bool enable;
	int mode;
};

bool getVEMode(JNIEnv * env, jobject obj, VEMode* pMode)
{
	bool result = false;
	do 
	{
		JniField fieldEnable(env, "com/gipsve/VEMode", obj, "Enable", "Z");
		if (!fieldEnable.isvalid())
			break;

		jboolean enable = fieldEnable.getBoolean();

		JniField fieldMode(env, "com/gipsve/VEMode", obj, "Mode", "I");
		if (!fieldMode.isvalid())
			break;

		jint mode = fieldMode.getInt();

		pMode->mode = (int)mode;
		pMode->enable = (bool)enable;

		result = true;

	} while (false);

	return result;
}

jobject newPPCodec(JNIEnv * env, PPCodec& codec)
{
	jclass cls_PPCodec = (env)->FindClass("com/gipsve/PPCodec");
	jmethodID mid = (env)->GetMethodID(cls_PPCodec, "<init>", "(ILjava/lang/String;IIII)V");
	return (env)->NewObject(cls_PPCodec, mid, (jint)codec.pltype, JniHelper::stoJstring(env, (char*)codec.plname),
		(jint)codec.plfreq, (jint)codec.pacsize, (jint)codec.channels, (jint)codec.rate);
}

jobject newVEMode(JNIEnv* env, bool enable, int mode)
{
	jclass cls_VEMode = (env)->FindClass("com/gipsve/VEMode");
	jmethodID mid = (env)->GetMethodID(cls_VEMode, "<init>", "(ZI)V");
	return (env)->NewObject(cls_VEMode, mid, (jboolean)enable, mode);
}

jobject newInteger(JNIEnv* env, int i)
{
	jclass cls_Integer = (env)->FindClass("java/lang/Integer");
	jmethodID mid = (env)->GetMethodID(cls_Integer, "<init>", "(I)V");
	return (env)->NewObject(cls_Integer, mid, i);
}

jobject newDeviceName(JNIEnv* env, char* name, char* guid)
{
	jclass cls_DeviceName = (env)->FindClass("com/gipsve/DeviceName");
	jmethodID mid = (env)->GetMethodID(cls_DeviceName, "<init>", "(Ljava/lang/String;Ljava/lang/String;)V");
	return (env)->NewObject(cls_DeviceName, mid, JniHelper::stoJstring(env, name), JniHelper::stoJstring(env, guid));
	
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    Init
 * Signature: (Ljava/lang/String;III)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_Init
  (JNIEnv * env, jclass cls, jstring auth, jint y, jint m, jint d)
{
	if(auth)
	{
		std::string str = JniHelper::jstringTostring(env, auth);
		return (jboolean)GIPSVE_Init((char*)str.c_str(), y, m, d);
	}
	else
	{
		return (jboolean)GIPSVE_Init(0, y, m, d);
	}
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    UnInit
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_gipsve_GipsVENative_UnInit
  (JNIEnv * env, jclass cls)
{
	GIPSVE_UnInit();
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    CreateChannel
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_gipsve_GipsVENative_CreateChannel
  (JNIEnv * env, jclass cls)
{
	return (jint)GIPSVE_CreateChannel();
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    DeleteChannel
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_DeleteChannel
  (JNIEnv * env, jclass cls, jint channel)
{
	return (jboolean)GIPSVE_DeleteChannel((int)channel);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetSendDestination
 * Signature: (ILjava/lang/String;S)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetSendDestination
  (JNIEnv * env, jclass cls, jint channel, jstring ip, jshort port)
{
	std::string str = JniHelper::jstringTostring(env, ip);
	return (jboolean)GIPSVE_SetSendDestination(channel, (char*)str.c_str(), (unsigned short)port);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetLocalReceiver
 * Signature: (IS)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetLocalReceiver
  (JNIEnv * env, jclass cls, jint channel, jshort port)
{
	return (jboolean)GIPSVE_SetLocalReceiver(channel, (unsigned short)port);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetSendCodec
 * Signature: (I)Lcom/gipsve/PPCodec;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetSendCodec
  (JNIEnv * env, jclass cls, jint channel)
{
	jobject result = 0;
	
	do 
	{
		PPCodec codec = {0};

		if(!GIPSVE_GetSendCodec(channel, codec))
			break;
		
		result = newPPCodec(env, codec);
		
	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetSendCodec
 * Signature: (ILcom/gipsve/PPCodec;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetSendCodec
  (JNIEnv * env, jclass cls, jint channel, jobject obj)
{
	jboolean result = (jboolean)false;
	PPCodec codec = {0};

	do 
	{
		JniField fieldType(env, "com/gipsve/PPCodec", obj, "Type", "I");
		if (!fieldType.isvalid())
			break;

		codec.pltype = fieldType.getInt();

		JniField fieldName(env, "com/gipsve/PPCodec", obj, "Name", "Ljava/lang/String;");
		if (!fieldName.isvalid())
			break;

		std::string name = JniHelper::jstringTostring(env, (jstring)fieldName.getObject());
		strcpy(codec.plname, name.c_str());

		JniField fieldFreq(env, "com/gipsve/PPCodec", obj, "Freq", "I");
		if (!fieldFreq.isvalid())
			break;

		codec.plfreq = fieldFreq.getInt();

		JniField fieldPacSize(env, "com/gipsve/PPCodec", obj, "PacSize", "I");
		if (!fieldPacSize.isvalid())
			break;

		codec.pacsize = fieldPacSize.getInt();

		JniField fieldChannels(env, "com/gipsve/PPCodec", obj, "Channels", "I");
		if (!fieldChannels.isvalid())
			break;

		codec.channels = fieldChannels.getInt();

		JniField fieldRate(env, "com/gipsve/PPCodec", obj, "Rate", "I");
		if (!fieldRate.isvalid())
			break;

		codec.rate = fieldRate.getInt();

		result = GIPSVE_SetSendCodec(channel, codec);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StartPlayout
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StartPlayout
  (JNIEnv * env, jclass cls, jint channel)
{
	return (jboolean)GIPSVE_StartPlayout(channel);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StopPlayout
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StopPlayout
  (JNIEnv * env, jclass cls, jint channel)
{
	return (jboolean)GIPSVE_StopPlayout(channel);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StartSend
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StartSend
  (JNIEnv * env, jclass cls, jint channel)
{
	return (jboolean)GIPSVE_StartSend(channel);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StopSend
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StopSend
  (JNIEnv * env, jclass cls, jint channel)
{
	return (jboolean)GIPSVE_StopSend(channel);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StartListen
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StartListen
  (JNIEnv * env, jclass cls, jint channel)
{
	return (jboolean)GIPSVE_StartListen(channel);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StopListen
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StopListen
  (JNIEnv * env, jclass cls, jint channel)
{
	return (jboolean)GIPSVE_StopListen(channel);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    PlayFileIn
 * Signature: (ILjava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_PlayFileIn
  (JNIEnv * env, jclass cls, jint channel, jstring filePath)
{
	return (jboolean)GIPSVE_PlayFileIn(channel, (char*)JniHelper::jstringTostring(env, filePath).c_str());
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StopPlayFileIn
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StopPlayFileIn
  (JNIEnv * env, jclass cls, jint channel)
{
	return (jboolean)GIPSVE_StopPlayFileIn(channel);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    PlayFileOut
 * Signature: (ILjava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_PlayFileOut
  (JNIEnv * env, jclass cls, jint channel, jstring filePath)
{
	return (jboolean)GIPSVE_PlayFileOut(channel, (char*)JniHelper::jstringTostring(env, filePath).c_str());
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StopPlayFileOut
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StopPlayFileOut
  (JNIEnv * env, jclass cls, jint channel)
{
	return (jboolean)GIPSVE_StopPlayFileOut(channel);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetVadMode
 * Signature: (ILcom/gipsve/VEMode;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetVadMode
  (JNIEnv * env, jclass cls, jint channel, jobject obj)
{
	VEMode mode = {0};
	if(!getVEMode(env, obj, &mode))
		return false;
	return (jboolean)GIPSVE_SetVadMode(channel, mode.enable, mode.mode);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetVadMode
 * Signature: (I)Lcom/gipsve/VEMode;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetVadMode
  (JNIEnv * env, jclass cls, jint channel)
{
	jobject result = 0;

	do 
	{
		bool enable = false;
		int mode = 0;
		if(!GIPSVE_GetVadMode(channel, enable, mode))
			break;

		result = newVEMode(env, enable, mode);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetMute
 * Signature: (IZ)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetMute
  (JNIEnv * env, jclass cls, jint channel, jboolean mute)
{
	return (jboolean)GIPSVE_SetMute(channel, mute);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    UseSRTPTx
 * Signature: (III)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_UseSRTPTx
  (JNIEnv * env, jclass cls, jint channel, jint useForRTP, jint useForRTCP)
{
	return (jboolean)GIPSVE_UseSRTPTx(channel, useForRTP, useForRTCP);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    UseSRTPRx
 * Signature: (III)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_UseSRTPRx
  (JNIEnv * env, jclass cls, jint channel, jint useForRTP, jint useForRTCP)
{
	return (jboolean)GIPSVE_UseSRTPRx(channel, useForRTP, useForRTCP);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetHoldMode
 * Signature: (ILcom/gipsve/VEMode;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetHoldMode
  (JNIEnv * env, jclass cls, jint channel, jobject obj)
{
	VEMode mode = {0};
	if(!getVEMode(env, obj, &mode))
		return false;
	return (jboolean)GIPSVE_SetHoldMode(channel, mode.enable, mode.mode);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetHoldMode
 * Signature: (I)Lcom/gipsve/VEMode;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetHoldMode
  (JNIEnv * env, jclass cls, jint channel)
{
	jobject result = 0;

	do 
	{
		bool enable = false;
		int mode = 0;
		if(!GIPSVE_GetHoldMode(channel, enable, mode))
			break;

		result = newVEMode(env, enable, mode);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetRxAgcMode
 * Signature: (ILcom/gipsve/VEMode;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetRxAgcMode
  (JNIEnv * env, jclass cls, jint channel, jobject obj)
{
	VEMode mode = {0};
	if(!getVEMode(env, obj, &mode))
		return false;
	return (jboolean)GIPSVE_SetRxAgcMode(channel, mode.enable, mode.mode);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetRxAgcMode
 * Signature: (I)Lcom/gipsve/VEMode;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetRxAgcMode
  (JNIEnv * env, jclass cls, jint channel)
{
	jobject result = 0;

	do 
	{
		bool enable = false;
		int mode = 0;
		if(!GIPSVE_GetRxAgcMode(channel, enable, mode))
			break;

		result = newVEMode(env, enable, mode);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetRxNsMode
 * Signature: (ILcom/gipsve/VEMode;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetRxNsMode
  (JNIEnv * env, jclass cls, jint channel, jobject obj)
{
	VEMode mode = {0};
	if(!getVEMode(env, obj, &mode))
		return false;
	return (jboolean)GIPSVE_SetRxNsMode(channel, mode.enable, mode.mode);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetRxNsMode
 * Signature: (I)Lcom/gipsve/VEMode;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetRxNsMode
  (JNIEnv * env, jclass cls, jint channel)
{
	jobject result = 0;

	do 
	{
		bool enable = false;
		int mode = 0;
		if(!GIPSVE_GetRxNsMode(channel, enable, mode))
			break;

		result = newVEMode(env, enable, mode);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StartRecordingMicrophone
 * Signature: (Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StartRecordingMicrophone
  (JNIEnv * env, jclass cls, jstring filepath)
{
	return (jboolean)GIPSVE_StartRecordingMicrophone((char*)JniHelper::jstringTostring(env, filepath).c_str());
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StopRecrodingMicrophone
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StopRecrodingMicrophone
  (JNIEnv * env, jclass cls)
{
	return (jboolean)GIPSVE_StopRecrodingMicrophone();
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StartRecordingPlayout
 * Signature: (ILjava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StartRecordingPlayout
  (JNIEnv * env, jclass cls, jint channel, jstring filepath)
{
	return (jboolean)GIPSVE_StartRecordingPlayout(channel, (char*)JniHelper::jstringTostring(env, filepath).c_str());
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    StopRecordingPlayout
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_StopRecordingPlayout
  (JNIEnv * env, jclass cls, jint channel)
{
	return (jboolean)GIPSVE_StopRecordingPlayout(channel);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetAgcMode
 * Signature: (Lcom/gipsve/VEMode;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetAgcMode
  (JNIEnv * env, jclass cls, jobject obj)
{
	VEMode mode = {0};
	if(!getVEMode(env, obj, &mode))
		return false;
	return (jboolean)GIPSVE_SetAgcMode(mode.enable, mode.mode);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetAgcMode
 * Signature: ()Lcom/gipsve/VEMode;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetAgcMode
  (JNIEnv * env, jclass cls)
{
	jobject result = 0;

	do 
	{
		bool enable = false;
		int mode = 0;
		if(!GIPSVE_GetAgcMode(enable, mode))
			break;

		result = newVEMode(env, enable, mode);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetNsMode
 * Signature: (Lcom/gipsve/VEMode;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetNsMode
  (JNIEnv * env, jclass cls, jobject obj)
{
	VEMode mode = {0};
	if(!getVEMode(env, obj, &mode))
		return false;
	return (jboolean)GIPSVE_SetNsMode(mode.enable, mode.mode);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetNsMode
 * Signature: ()Lcom/gipsve/VEMode;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetNsMode
  (JNIEnv * env, jclass cls)
{
	jobject result = 0;

	do 
	{
		bool enable = false;
		int mode = 0;
		if(!GIPSVE_GetNsMode(enable, mode))
			break;

		result = newVEMode(env, enable, mode);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetEcMode
 * Signature: (Lcom/gipsve/VEMode;)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetEcMode
  (JNIEnv * env, jclass cls, jobject obj)
{
	VEMode mode = {0};
	if(!getVEMode(env, obj, &mode))
		return false;
	return (jboolean)GIPSVE_SetEcMode(mode.enable, mode.mode);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetEcMode
 * Signature: ()Lcom/gipsve/VEMode;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetEcMode
  (JNIEnv * env, jclass cls)
{
	jobject result = 0;

	do 
	{
		bool enable = false;
		int mode = 0;
		if(!GIPSVE_GetEcMode(enable, mode))
			break;

		result = newVEMode(env, enable, mode);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetCPULoad
 * Signature: ()Ljava/lang/Integer;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetCPULoad
  (JNIEnv * env, jclass cls)
{
	jobject result = 0;

	do 
	{
		int loadPercent = 0;

		if(!GIPSVE_GetCPULoad(loadPercent))
			break;

		result = newInteger(env, loadPercent);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetSystemCPULoad
 * Signature: ()Ljava/lang/Integer;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetSystemCPULoad
  (JNIEnv * env, jclass cls)
{
	jobject result = 0;

	do 
	{
		int loadPercent = 0;

		if(!GIPSVE_GetSystemCPULoad(loadPercent))
			break;

		result = newInteger(env, loadPercent);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetNumberOfCodecs
 * Signature: ()Ljava/lang/Integer;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetNumberOfCodecs
  (JNIEnv * env, jclass cls)
{
	return newInteger(env, GIPSVE_GetNumberOfCodecs());
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetCodec
 * Signature: (I)Lcom/gipsve/PPCodec;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetCodec
  (JNIEnv * env, jclass cls, jint index)
{
	jobject result = 0;

	do 
	{
		PPCodec codec = {0};
		if(!GIPSVE_GetCodec(index, codec))
			break;

		result = newPPCodec(env, codec);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetNumberOfPlayoutDevice
 * Signature: ()Ljava/lang/Integer;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetNumberOfPlayoutDevice
  (JNIEnv * env, jclass cls)
{
	jobject result = 0;

	do 
	{
		int nb = 0;

		if(!GIPSVE_GetNumberOfPlayoutDevice(nb))
			break;

		result = newInteger(env, nb);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetPlayoutDeviceName
 * Signature: (I)Lcom/gipsve/DeviceName;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetPlayoutDeviceName
  (JNIEnv * env, jclass cls, jint index)
{
	jobject result = 0;

	do 
	{
		char name[128] = {0};
		char guid[128] = {0};

		if(!GIPSVE_GetPlayoutDeviceName(index, name, guid))
			break;

		result = newDeviceName(env, name, guid);

	} while (false);

	return result;
	
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetRecordingDeviceName
 * Signature: (I)Lcom/gipsve/DeviceName;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetRecordingDeviceName
  (JNIEnv * env, jclass cls, jint index)
{
	jobject result = 0;

	do 
	{
		char name[128] = {0};
		char guid[128] = {0};

		if(!GIPSVE_GetRecordingDeviceName(index, name, guid))
			break;

		result = newDeviceName(env, name, guid);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetPlayoutDevice
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetPlayoutDevice
  (JNIEnv * env, jclass cls, jint index)
{
	return (jboolean)GIPSVE_SetPlayoutDevice(index);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetRecordingDevice
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetRecordingDevice
  (JNIEnv * env, jclass cls, jint index)
{
	return (jboolean) GIPSVE_SetRecordingDevice(index);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetMicVolume
 * Signature: ()Ljava/lang/Integer;
 */
JNIEXPORT jobject JNICALL Java_com_gipsve_GipsVENative_GetMicVolume
  (JNIEnv * env, jclass cls)
{
	jobject result = 0;

	do 
	{
		unsigned int volume = 0;

		if(!GIPSVE_GetMicVolume(volume))
			break;

		result = newInteger(env, (int)volume);

	} while (false);

	return result;
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetMicVolume
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetMicVolume
  (JNIEnv * env, jclass cls, jint volume)
{
	return (jboolean)GIPSVE_SetMicVolume(volume);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    SetSpeakerVolume
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL Java_com_gipsve_GipsVENative_SetSpeakerVolume
  (JNIEnv * env, jclass cls, jint volume)
{
	return (jboolean)GIPSVE_SetSpeakerVolume(volume);
}

/*
 * Class:     com_gipsve_GipsVENative
 * Method:    GetLastError
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_gipsve_GipsVENative_GetLastError
  (JNIEnv * env, jclass cls)
{
	return (jint)GIPSVE_LastError();
}